package me.spring.cloud.common.components.util.http;


import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.Method;
import me.spring.cloud.common.components.util.lang.StringUtil;
import me.spring.cloud.common.components.util.net.DomainUtil;
import me.spring.cloud.common.components.util.net.InnerIp;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Random;

/**
 * @author luffy
 * @description: 自定义请求工具
 * @date 2019-06-24 10:03
 */
public class HttpReqUtil {

  public static String Header_Accept = "Accept";
  public static String Header_X_Forwarded_For = "X-Forwarded-For";
  public static String Header_remote_addr = "remote_addr";
  public static String Header_Host = "Host";
  public static String Header_Refer = "Refer";
  public static String Header_Proxy_Client_IP = "Proxy-Client-IP";
  public static String Header_X_Real_IP = "X-Real-IP";
  public static String Header_WL_Proxy_Client_IP = "WL-Proxy-Client-IP";
  public static String Header_HTTP_CLIENT_IP = "HTTP_CLIENT_IP";
  public static String Header_HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR";
  public static String Header_User_Agent = "User-Agent";
  public static String Header_Language = "Accept-Language";
  public static String Header_HTTP_VIA = "HTTP_VIA";
  public static String Header_Accept_Encoding = "Accept-Encoding";
  public static String Header_Upgrade_Insecure_Requests = "Upgrade-Insecure-Requests";

  private static final String[] accept = {
      "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
      "image/png,image/*;q=0.8,*/*;q=0.5",
      "*/*",
      "image/png,image/*;q=0.8,*/*;q=0.5",
      "text/css,*/*;q=0.1",
      "text/javascript, application/javascript, */*",
      "text/html,application/xml;q=0.9,application/xhtml+xml,image/png,image/jpeg,image/gif,image/x-xbitmap,*/*;q=0.1",
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"
  };

  private static String[] Accept_Encoding = {
      "gzip",
      "gzip, deflate, br"
  };

  private static String[] Accept_Languages = {
      "zh,en;q=0.9,zh-CN;q=0.8",
      "zh,en;q=0.9,zh-CN;q=0.8",
      "zh,en;q=0.9,zh-CN;q=0.8"
  };

  /**
   * @Return java.lang.String
   * @Author luffy
   * @Description 随机生成ip
   * @Date 2019-06-24 10:06
   * @Param []
   **/
  public static String randomIP() {
    return RandomUtil.randomInt(1, 255)
        + "." + RandomUtil.randomInt(1, 255) + "." + RandomUtil.randomInt(1, 255) + "." + RandomUtil
        .randomInt(1, 254);
  }

  /**
   * @Author luffy
   * @Description 随机内网ip
   * @Param
   * @Return java.lang.String
   * @Date 2019-09-06 11:44
   */
  public static String randomInnerIp() {
    int i = RandomUtil.randomInt(InnerIp.values().length);
    InnerIp[] ips = InnerIp.values();
    return NetUtil.longToIpv4(RandomUtil.randomLong(ips[i].getBeg(), ips[i].getEnd() + 1));
  }

  /**
   * @Author luffy
   * @Description 随机生成国内ip
   * @Param
   * @Return java.lang.String
   * @Date 2019-09-04 16:44
   */
  public static String getRandomInternalIp() {
    // 需要排除监控的ip范围
    int[][] range = {{607649792, 608174079}, // 36.56.0.0-36.63.255.255
        {1038614528, 1039007743}, // 61.232.0.0-61.237.255.255
        {1783627776, 1784676351}, // 106.80.0.0-106.95.255.255
        {2035023872, 2035154943}, // 121.76.0.0-121.77.255.255
        {2078801920, 2079064063}, // 123.232.0.0-123.235.255.255
        {-1950089216, -1948778497}, // 139.196.0.0-139.215.255.255
        {-1425539072, -1425014785}, // 171.8.0.0-171.15.255.255
        {-1236271104, -1235419137}, // 182.80.0.0-182.92.255.255
        {-770113536, -768606209}, // 210.25.0.0-210.47.255.255
        {-569376768, -564133889}, // 222.16.0.0-222.95.255.255
    };

    Random rdint = new Random();
    int index = rdint.nextInt(range.length);
    String ip = num2ip(range[index][0] + new Random().nextInt(range[index][1] - range[index][0]));
    return ip;
  }

  /**
   * @Author luffy
   * @Description 将十进制转换成IP地址
   * @Param ip
   * @Return java.lang.String
   * @Date 2019-09-04 16:41
   */
  private static String num2ip(int ip) {
    int[] b = new int[4];
    b[0] = (ip >> 24) & 0xff;
    b[1] = (ip >> 16) & 0xff;
    b[2] = (ip >> 8) & 0xff;
    b[3] = ip & 0xff;
    return b[0] + "." + b[1] + "." + b[2] + "." + b[3];
  }

  /**
   * @Author luffy
   * @Description get请求
   * @Param url
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:03
   */
  public static HttpReqResponse getResponse(String url, Integer timeoutSecond) {
    return executeHttp(createHttpRequest(url, null, null, false, Method.GET, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description get请求
   * @Param url
   * @Param headers
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:05
   */
  public static HttpReqResponse getResponse(String url, Map<String, String> headers, Integer timeoutSecond) {
    return executeHttp(createHttpRequest(url, null, headers, false, Method.GET, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description get请求(头信息 - 固定ip)
   * @Param url
   * @Param ip
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:03
   */
  public static HttpReqResponse getResponseByIp(String url, String ip, Integer timeoutSecond) {
    return executeHttp(createHttpRequest(url, ip, null, false, Method.GET, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description get请求，随机ip
   * @Param url
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:04
   */
  public static HttpReqResponse getResponseForRdmIp(String url, Integer timeoutSecond) {
    // 随机生成IP
    String ip = randomIP();
    return executeHttp(createHttpRequest(url, ip, null, true, Method.GET, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description get请求，随机头
   * @Param url
   * @Param headers
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:04
   */
  public static HttpReqResponse getResponseForRdmIp(String url, Map<String, String> headers, Integer timeoutSecond) {
    // 随机生成IP
    String ip = randomIP();
    return executeHttp(createHttpRequest(url, ip, headers, true, Method.GET, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post请求json数据
   * @Param url
   * @Param header
   * @Param body json数据
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:06
   */
  public static HttpReqResponse postResponse(String url, Map<String, String> header, String body,
      Integer timeoutSecond) {
    return executeHttp(createPostBody(url, null, header, false, body, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post请求
   * @Param url
   * @Param header
   * @Param rdmui 是否随机ip和ua
   * @Param params
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:08
   */
  public static HttpReqResponse postResponse(String url, Map<String, String> header, boolean rdmui,
      Map<String, Object> params, Integer timeoutSecond) {
    return executeHttp(createPostParams(url, null, header, rdmui, params, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post请求，固定ip
   * @Param url
   * @Param ip
   * @Param body json字符串
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:09
   */
  public static HttpReqResponse postResponseByIp(String url, String ip, String body, Integer timeoutSecond) {
    return executeHttp(createPostBody(url, ip, null, false, body, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post请求
   * @Param url
   * @Param ip
   * @Param header
   * @Param userRdmHead
   * @Param params
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:10
   */
  public static HttpReqResponse postResponseByIp(String url, String ip, Map<String, String> header,
      boolean userRdmHead, Map<String, Object> params, Integer timeoutSecond) {
    return executeHttp(createPostParams(url, ip, header, userRdmHead, params, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post请求
   * @Param url
   * @Param body json字符串
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:17
   */
  public static HttpReqResponse postResponseForRdmIp(String url, String body, Integer timeoutSecond) {
    String ip = randomIP();
    return executeHttp(createPostBody(url, ip, null, true, body, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post body
   * @Param url
   * @Param body
   * @Param header
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 11:10
   */
  public static HttpReqResponse postResponseForRdmIp(String url, Map<String, String> header, String body,
      Integer timeoutSecond) {
    String ip = randomIP();
    return executeHttp(createPostBody(url, ip, header, true, body, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post form
   * @Param url
   * @Param params
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:23
   */
  public static HttpReqResponse postResponseForRdmIp(String url, Map<String, Object> params, Integer timeoutSecond) {
    String ip = randomIP();
    return executeHttp(createPostParams(url, ip, null, true, params, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description post form
   * @Param url
   * @Param params
   * @Param header
   * @Param timeoutSecond
   * @Return HttpReqResponse
   * @Date 2019-09-06 13:23
   */
  public static HttpReqResponse postResponseForRdmIp(String url, Map<String, String> header,Map<String, Object> params,
      Integer timeoutSecond) {
    String ip = randomIP();
    return executeHttp(createPostParams(url, ip, header, true, params, timeoutSecond));
  }

  /**
   * @Author luffy
   * @Description 执行
   * @Param request
   * @Return HttpReqResponse
   * @Date 2019-08-23 12:53
   */
  private static HttpReqResponse executeHttp(HttpRequest request) {
    try {
      return new HttpReqResponse(request.execute());
    } catch (HttpException he) {
      if (he.getCause() instanceof UnknownHostException) {
        return new HttpReqResponse(HttpRspStatus.HTTP_UN_KNOW_HOST, he.getCause().getMessage());
      }
      if (he.getCause() instanceof SocketTimeoutException) {
        return new HttpReqResponse(HttpRspStatus.HTTP_TIME_OUT, he.getCause().getMessage());
      }
      return new HttpReqResponse(HttpRspStatus.HTTP_OTHER, he.getMessage());
    }
  }


  /**
   * @param url
   * @param ip
   * @param requestType
   * @param timeoutSecond
   * @Return cn.hutool.http.HttpRequest
   * @Author luffy
   * @Description 构造请求
   * @Date 2019-08-08 15:38
   */
  private static HttpRequest createHttpRequest(String url, String ip, Map<String, String> headers, boolean userRdmHead,
      Method requestType,
      Integer timeoutSecond) {
    HttpRequest request;
    if (Method.POST.equals(requestType)) {
      request = HttpRequest.post(url);
    } else if (Method.HEAD.equals(requestType)) {
      request = HttpRequest.head(url);
    } else if (Method.OPTIONS.equals(requestType)) {
      request = HttpRequest.options(url);
    } else if (Method.PUT.equals(requestType)) {
      request = HttpRequest.put(url);
    } else if (Method.DELETE.equals(requestType)) {
      request = HttpRequest.delete(url);
    } else if (Method.TRACE.equals(requestType)) {
      request = HttpRequest.trace(url);
    } else if (Method.PATCH.equals(requestType)) {
      request = HttpRequest.patch(url);
    } else {
      request = HttpRequest.get(url);
    }
    if (userRdmHead) {
      request.header(Header_Upgrade_Insecure_Requests, "1")
          .header(Header_Accept, accept[RandomUtil.randomInt(accept.length)])
          .header(Header_Accept_Encoding, Accept_Encoding[RandomUtil.randomInt(Accept_Encoding.length)])
          .header(Header_Language, Accept_Languages[RandomUtil.randomInt(Accept_Languages.length)])
          .header(Header_Host, DomainUtil.getDomain(url));
    }
    if (!StringUtil.isEmpty(ip)) {
      request = request.header(Header_remote_addr, ip, true);
    }
    if (null != headers && !headers.isEmpty()) {
      request.headerMap(headers, true);
    }
    if (null != timeoutSecond && 0 != timeoutSecond) {
      request = request.timeout(timeoutSecond * 1000);
    }
    return request;
  }

  /**
   * @param url
   * @param ip
   * @param params
   * @param timeoutSecond
   * @Return cn.hutool.http.HttpRequest
   * @Author luffy
   * @Description 构造post form
   * @Date 2019-08-08 15:50
   */
  private static HttpRequest createPostParams(String url, String ip, Map<String, String> header,
      boolean userRdmHead, Map<String, Object> params, Integer timeoutSecond) {
    HttpRequest request = createHttpRequest(url, ip, header, userRdmHead, Method.POST, timeoutSecond);
    if (null != params && !params.isEmpty()) {
      request.form(params);
    }
    return request;
  }

  /**
   * @param url
   * @param ip
   * @param body
   * @param timeoutSecond
   * @Return cn.hutool.http.HttpRequest
   * @Author luffy
   * @Description 构造post body
   * @Date 2019-08-08 15:50
   */
  private static HttpRequest createPostBody(String url, String ip, Map<String, String> header, boolean userRdmHead,
      String body, Integer timeoutSecond) {
    HttpRequest request = createHttpRequest(url, ip, header, userRdmHead, Method.POST, timeoutSecond);
    if (!StringUtil.isEmpty(body)) {
      request.body(body);
    }
    return request;
  }

  /**
   * @Author luffy
   * @Description 创建代理
   * @Param ip
   * @Param port
   * @Return java.net.Proxy
   * @Date 2019-09-20 11:36
   */
  public static Proxy createProxy(String ip,int port){
    return new Proxy(Proxy.Type.HTTP,
        new InetSocketAddress(ip, port));
  }

}
